#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include<windows.h>
#include<time.h>

#define high 20    //定义游戏画面尺寸
#define width 30 

//全局变量
int food_x,food_y;    //记录食物位置 
int movedirection;   //小蛇移动方向，1，2，3，4分别表示上下左右 
int canvas[high][width]={0};  //二维数组记录游戏画面中对应的元素
//0输出空格，-1输出边框#，1输出蛇头@，>1输出蛇身*，-2为食物$ 


void gotoxy(int x,int y)//光标移动到（x，y）位置
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle,pos);
}

void HideCursor()
{
	CONSOLE_CURSOR_INFO cursor_info = {1,0}; // 第二个值为0表示隐藏光标
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}

void satrtup()//数据初始化
{
	int i,j;
	//以下设定边框的数值 
	for(i=0;i<high;i++)
	{
		canvas[i][0]=-1;
		canvas[i][width-1]=-1;
	}
	for(j=0;j<width;j++)
	{
		canvas[0][j]=-1;
		canvas[high-1][j]=-1;
	}
	
	//以下初始化蛇头蛇身
	canvas[high/2][width/2]=1;
	
	for(i=0;i<=4;i++) 
		canvas[high/2][width/2-i]=i+1;
	
	//初始化小蛇移动方向右 
	movedirection=4;
	
	//初始化食物位置 
	food_x=rand()%(high-5)+2;
	food_y=rand()%(width-5)+2;	
	canvas[food_x][food_y]=-2;
	
	HideCursor(); //隐藏光标 
}

void movesnakebydirection()
{
	int i,j;
	int max=0;
	int oldtail_i,oldtail_j;  //记录旧蛇尾 
	int oldhead_i,oldhead_j;  //记录旧蛇头 
	
	for(i=1;i<high-1;i++)
		for(j=1;j<width-1;j++)
		{
			if(canvas[i][j]>0)
			{
				//对所有大于0的元素加一
				canvas[i][j]++;
				
				//求出最大值max 
				if(max<canvas[i][j])
				{
					max=canvas[i][j];
					oldtail_i=i;
					oldtail_j=j;
				} 
				
				//记录旧蛇头位置 
				if(canvas[i][j]==2)
				{
					oldhead_i=i;
					oldhead_j=j;
				}
				 
			}
		}
	
	int newhead_i,newhead_j;
	
	if(movedirection==1)  //向上
	{
		newhead_i=oldhead_i-1;
		newhead_j=oldhead_j;
	}
	if(movedirection==2)  //向下 
	{
		newhead_i=oldhead_i+1;
		newhead_j=oldhead_j;
	}
	if(movedirection==3)  //向左
	{
		newhead_i=oldhead_i;
		newhead_j=oldhead_j-1;
	}
	if(movedirection==4)  //向右
	{
		newhead_i=oldhead_i;
		newhead_j=oldhead_j+1;
	}
	
	//判断蛇头是否碰到食物
	if(canvas[newhead_i][newhead_j]==-2) 
	{
		//食物原始位置归0 
		canvas[food_x][food_y]=0;
		//产生新的食物 
		food_x=rand()%(high-5)+2;
		food_y=rand()%(width-5)+2;	
		canvas[food_x][food_y]=-2;
		
		//吃到食物不用把最大值变0，长度加一 
	}
	else
	{
		//没有吃到食物，长度不变 
		canvas[oldtail_i][oldtail_j]=0;   //最大值所在元素变为0 
	}
	
	//判断蛇头撞到边框或自身，游戏失败
	if(canvas[newhead_i][newhead_j]>0 || canvas[newhead_i][newhead_j]==-1) 
	{
		printf("游戏失败\n");
		exit(0);
	}
	else
	{
		canvas[newhead_i][newhead_j]=1;
	}
} 


void show()//显示画面
{
	gotoxy(0,0); // 光标移动到原点位置，以下重画清屏
	
	int i,j;
	for(i=0;i<high;i++)
	{
		for (j=0;j<width;j++)
		{
			if(canvas[i][j]==0)
				printf(" ");     //输出空格 
			else if (canvas[i][j]==-1)
				printf("#");    //输出边框# 
			else if (canvas[i][j]==1)
				printf("@");    //输出蛇头@ 
			else if (canvas[i][j]>1)
				printf("*");    //输出蛇身* 
			else if (canvas[i][j]==-2)
				printf("$");    //输出食物$
		}
		printf("\n");
	}
	
	Sleep(200);
}
void updateWithoutInput()//与用户输入无关的更新
{
	movesnakebydirection(); 
}
void updateWithInput()//与用户输入有关的更新
{
	char input;
	if(kbhit()) 
	{
		input=getch();
		if(input=='a')
			movedirection=3;
		if(input=='d')
			movedirection=4;
		if(input=='w')
			movedirection=1;
		if(input=='s')
			movedirection=2;
	}
}
int main() 
{
	satrtup();//数据初始化
    while(1)//游戏循环执行
	{
		show();//显示画面
		updateWithoutInput();//与用户输入无关的更新
		updateWithInput();//与用户输入有关的更新
	}
	return 0;
}
